import _ from 'lodash';
import { AgentDto, AgentPageQuery } from '../dtos';
import { AgentRepository } from '../repositories';
import { getCustomRepository } from 'typeorm';
import { entityToDto, dtoToEntity } from '../assembler';
import { Agent } from '../entities/agent';
export interface IAgentService {
  findAll(): Promise<AgentDto[]>;
  findById(id: number): Promise<AgentDto | undefined>;
  findByIdentity(identity: string): Promise<AgentDto | undefined>;
  findByProduct(product: string): Promise<AgentDto[]>;
  findByProductAndStatus(product: string, status: string): Promise<AgentDto[]>;
  save(dto: AgentDto): Promise<number>;
  findByIdentitiesAndStatus(identities: string[], status: string): Promise<AgentDto[]>;
  findForPage(pageQuery: AgentPageQuery): Promise<any>;
}

class AgentService implements IAgentService {

  private agentRepository: AgentRepository;

  init() {
    this.agentRepository = getCustomRepository(AgentRepository);
  }

  public async findByProductAndStatus(product: string, status: string): Promise<AgentDto[]> {
    const agents = await this.agentRepository.findByProductAndStatus(product, status);
    return agents.map(agentEntity => entityToDto(agentEntity));
  }

  public async findById(id: number): Promise<AgentDto | undefined> {
    const agentEntity = await this.agentRepository.findOne(id);
    if (agentEntity) {
      return entityToDto(agentEntity);
    }
  }

  async findAll(): Promise<AgentDto[]> {
    const agents = await this.agentRepository.find();
    return agents.map(agentEntity => entityToDto(agentEntity));
  }

  async findByIdentity(identity: string): Promise<AgentDto | undefined> {
    const agent = await this.agentRepository.findByIdentity(identity);
    if (agent) {
      return entityToDto(agent);
    }
  }

  async save(dto: AgentDto): Promise<number> {
    const agentEntity = this.agentRepository.create(dtoToEntity(dto));
    await this.agentRepository.save(agentEntity);
    return agentEntity.id;
  }

  async saveOrUpdateByIdentity(dto: AgentDto) {
    const agentEntity = await this.agentRepository.findByIdentity(dto.identity);
    if (agentEntity) {
      await this.save({ ...agentEntity, ... dto });
    } else {
      await this.save(dto);
    }
  }

  async updateByIdentity(agent: Agent) {
    const agentEntity = await this.agentRepository.findByIdentity(agent.identity);
    if (agentEntity) {
      await this.agentRepository.save({ ...agentEntity, ... agent });
    }
  }

  async findByProduct(product: string): Promise<AgentDto[]> {
    const agentEntities = await this.agentRepository.findByProduct(product);
    return agentEntities.map(agentEntity => entityToDto(agentEntity));
  }

  public async findByIdentitiesAndStatus(identities: string[], status: string): Promise<AgentDto[]> {
    if (_.isEmpty(identities)) { return []; }
    const agents = await this.agentRepository.findByIdentitiesAndStatus(identities, status);
    return agents.map(agentEntity => entityToDto(agentEntity));
  }

  async findForPage(pageQuery: AgentPageQuery): Promise<any> {
    const pageData = await this.agentRepository.findForPage(pageQuery);
    pageData.data = pageData.data.map(job => entityToDto(job));
    return pageData;
  }


}

export const agentService = new AgentService();